package com.xwltz.core.utils;

import cn.hutool.core.util.XmlUtil;
import org.dom4j.*;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description XmlUtils
 * @information on version 1.0 be created by @xwltz at 2022/5/11 17:53
 */
public class XmlUtils extends XmlUtil {

	/**
	 * 解析xml为map
	 *
	 * @param xml xmlString
	 * @return map
	 */

	public static Map<String, Object> decodeXml2Map(@Nonnull String xml) throws DocumentException {
		Map<String, Object> result = new HashMap<>();
		Document document = readXml2Document(xml);
		element2Object(document.getRootElement(), result);
		return result;
	}

	public static Map<String, Object> decodeSimpleXml(@Nonnull String xml) throws DocumentException {
		Map<String, Object> result = new HashMap<>();
		Document document = readXml2Document(xml);
		Element root = document.getRootElement();
		element2Nodes(root, result);
		return result;
	}

	private static Document readXml2Document(String xml) throws DocumentException {
		Document document = DocumentHelper.parseText(xml.trim());
		document.setXMLEncoding("utf-8");
		return document;
	}

	/**
	 * 将元素转为对象Map
	 *
	 * @param element 元素
	 * @param obj map
	 */
	@SuppressWarnings("unchecked")
	private static void element2Object(Element element, Map<String, Object> obj) {
		if (element.getNodeType() == Node.CDATA_SECTION_NODE) {
			obj.put("/", element.getStringValue());
		} else {
			obj.put("/", element.getText().trim());
		}
		Attribute attribute;
		for (int i = 0; i < element.attributeCount(); i++) {
			attribute = element.attribute(i);
			obj.put(attribute.getName(), attribute.getValue());
		}

		if (element.elements().size() > 0) {
			Element tempElement;
			for (int i = 0; i < element.elements().size(); i++) {
				tempElement = element.elements().get(i);

				Map<String, Object> leafNode = new HashMap<>();
				element2Object(tempElement, leafNode);
				if (element.elements(tempElement.getName()).size() > 1) {
					List<Map<String, Object>> leafList;
					if (obj.containsKey(tempElement.getName())) {
						leafList = (List<Map<String, Object>>) obj.get(tempElement.getName());
					} else {
						leafList = new ArrayList<>();
						obj.put(tempElement.getName(), leafList);
					}

					leafList.add(leafNode);
				} else {
					obj.put(tempElement.getName(), leafNode);
				}
			}
		}
	}


	private static void element2Nodes(Element element, Map<String, Object> nodes) {
		nodes.put(element.getName(), element.getNodeType() == Node.CDATA_SECTION_NODE ? element.getStringValue() : element.getText().trim());
		if (element.elements().size() > 0) {
			Map<String, Object> leafNode = new HashMap<>();
			nodes.put(element.getName(), leafNode);
			Element tempElement;
			for (int i = 0; i < element.elements().size(); i++) {
				tempElement = element.elements().get(i);
				element2Nodes(tempElement, leafNode);
			}
		}
	}
}
